#pragma once
#include <iostream>
#include <map>
#include <string>

/**
 * @brief 
 */
class IExpression
{
public:
	virtual int Interpret(const std::map<std::string, int> mapContext) = 0;

	virtual ~IExpression() = default;
};

class Variable : public IExpression 
{
public:
	explicit Variable(const std::string& strName)
		: _strName(strName)
	{}

	virtual int Interpret(const std::map<std::string, int> mapContext)
	{
		return mapContext.at(_strName);
	}

private:
	std::string _strName{};
};

class Add : public IExpression
{
public:
	Add(std::shared_ptr<IExpression> left, std::shared_ptr<IExpression> right)
		: _left(left), _right(right)
	{
	}

	virtual int Interpret(const std::map<std::string, int> mapContext)
	{
		return _left->Interpret(mapContext) + _right->Interpret(mapContext);
	}

private:
	std::shared_ptr<IExpression> _left;
	std::shared_ptr<IExpression> _right;
};